package contract

import (
	"context"
	"crypto/ecdsa"
	"fmt"
	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/ethclient"
	tronWallet "github.com/ranjbar-dev/tron-wallet"
	"github.com/ranjbar-dev/tron-wallet/enums"
	"log"
	"math/big"
	"signature-service/contract/evmAbi"
	"strings"
	"time"
)

func GetTransactionMainSigned(client *ethclient.Client, privateKey *ecdsa.PrivateKey, value *big.Int, toAddress common.Address) (*types.Transaction, error) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()

	// 构建交易参数
	nonce, err := client.PendingNonceAt(context.Background(), crypto.PubkeyToAddress(privateKey.PublicKey))
	if err != nil {
		log.Printf("Failed to retrieve nonce: %v", err)
		return nil, err
	}

	gasPrice, err := client.SuggestGasPrice(context.Background())
	if err != nil {
		log.Printf("Failed to retrieve gas price: %v", err)
		return nil, err
	}
	var Data []byte
	//gasLimit := uint64(300000) // 自定义燃气限制
	gasLimit, err := client.EstimateGas(ctx, ethereum.CallMsg{
		From: crypto.PubkeyToAddress(privateKey.PublicKey), // 设置调用者地址
		To:   &toAddress,
		Data: Data,
	})
	// 创建交易
	//tx := types.NewTransaction(nonce, toAddress, value, gasLimit, gasPrice, Data)
	// 设置过期时间为60秒后
	//expirationTime := time.Now().Unix() + 60 // 当前时间 + 60秒
	//expirationData := append(Data, big.NewInt(expirationTime).Bytes()...)
	var legacyTx types.LegacyTx
	legacyTx.Data = Data
	legacyTx.Nonce = nonce
	legacyTx.To = &toAddress
	legacyTx.Value = value
	legacyTx.GasPrice = gasPrice
	legacyTx.Gas = gasLimit
	tx := types.NewTx(&legacyTx)
	ChainID, err := client.ChainID(ctx)
	if err != nil {
		log.Printf("Failed to ChainID: %v", err)
		return nil, err
	}
	// 签名交易
	signedTx, err := types.SignTx(tx, types.NewEIP155Signer(ChainID), privateKey)
	if err != nil {
		log.Printf("Failed to sign transaction: %v", err)
		return nil, err
	}

	//// 发送交易
	//err = client.SendTransaction(context.Background(), signedTx)
	//if err != nil {
	//	log.Printf("Failed to send transaction: %v", err)
	//	return nil, err
	//}
	return signedTx, nil
}

func GetTransactionTrxMainSigned(rpcUrl string, privateKey string, value int64, toAddress string) (string, error) {
	node := enums.CreateNode(rpcUrl)
	c := &tronWallet.Crawler{
		Node: node,
	}

	f, err := tronWallet.CreateTronWallet(c.Node, privateKey)
	if err != nil {
		log.Printf("TRX充币监控，创建手续费钱包失败 %s", err.Error())
	}

	txId, err := f.Transfer(toAddress, value)
	if err != nil {
		return "", err
	}
	return txId, nil
}
func GetTransactionSigned(client *ethclient.Client, privateKey *ecdsa.PrivateKey, contractAddress common.Address, contractABI string, methodName string, params ...interface{}) (*types.Transaction, error) {
	// 使用带有超时的上下文是一个好习惯
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()

	// 获取当前链的ID
	ChainID, err := client.ChainID(ctx)
	if err != nil {
		return nil, err
	}

	// 获取发送者地址
	fromAddress := crypto.PubkeyToAddress(privateKey.PublicKey)

	// 获取账户的nonce值
	nonce, err := client.PendingNonceAt(ctx, fromAddress)
	if err != nil {
		return nil, fmt.Errorf("获取nonce失败: %v", err)
	}
	// 获取当前推荐的gas价格
	gasPrice, err := client.SuggestGasPrice(ctx)
	if err != nil {
		return nil, fmt.Errorf("获取gas价格失败: %v", err)
	}

	// 解析合约ABI
	parsedABI, err := abi.JSON(strings.NewReader(contractABI))
	if err != nil {
		return nil, fmt.Errorf("解析合约ABI失败: %v", err)
	}
	//for _, param := range params {
	//	log.Printf("%v", param)
	//}
	// 打包要调用的合约方法和参数
	input, err := parsedABI.Pack(methodName, params...)
	if err != nil {
		return nil, fmt.Errorf("打包输入数据失败: %v", err)
	}
	//time.Sleep(15 * time.Second)
	// 估算调用方法所需的gas限制
	gasLimit, err := client.EstimateGas(ctx, ethereum.CallMsg{
		From: fromAddress, // 设置调用者地址
		To:   &contractAddress,
		Data: input,
	})
	if err != nil {
		//去授权
		if err.Error() == "execution reverted: TransferHelper::transferFrom: transferFrom failed" {
			//去授权
			arr := params[2].([]common.Address)[0]
			fmt.Println(arr)
			SendApprove(client, privateKey, contractAddress, evmAbi.ERC20_ABI, params[2].([]common.Address)[0], params[0].(*big.Int))
		}
		//gasLimit = uint64(14400000)
		//fmt.Errorf("估算gas失败: %v", err.Error())
		return nil, fmt.Errorf("估算gas失败: %v", err.Error())
	}

	// 创建交易
	//tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, input)
	// 设置过期时间为60秒后
	//expirationTime := time.Now().Unix() + 60 // 当前时间 + 60秒
	//expirationData := append(input, big.NewInt(expirationTime).Bytes()...)
	var legacyTx types.LegacyTx
	legacyTx.Data = input
	legacyTx.Nonce = nonce
	legacyTx.To = &contractAddress
	legacyTx.Value = big.NewInt(0)
	legacyTx.GasPrice = gasPrice
	legacyTx.Gas = gasLimit
	tx := types.NewTx(&legacyTx)

	// 对交易进行签名，注意这里使用了EIP155签名者，并且需要正确的chainID
	signedTx, err := types.SignTx(tx, types.NewEIP155Signer(ChainID), privateKey)
	if err != nil {
		return nil, fmt.Errorf("签名交易失败: %v", err)
	}

	//// 发送交易
	//err = client.SendTransaction(ctx, signedTx)
	//if err != nil {
	//	return nil, fmt.Errorf("发送交易失败: %v", err)
	//}

	return signedTx, nil
}

func GetTransactionTrxSigned(rpcUrl string, privateKey string, value int64, toAddress string, tokenAddress string) (string, error) {
	node := enums.CreateNode(rpcUrl)
	c := &tronWallet.Crawler{
		Node: node,
	}

	f, err := tronWallet.CreateTronWallet(c.Node, privateKey)
	if err != nil {
		log.Printf("TRX充币监控，创建手续费钱包失败 %s", err.Error())
	}

	//进行归集操作
	token := &tronWallet.Token{
		ContractAddress: enums.CreateContractAddress(tokenAddress),
	}
	txId, err := f.TransferTRC20(token, toAddress, value)
	if err != nil {
		return "", err
	}
	return txId, nil
}
func SendApprove(client *ethclient.Client, privateKey *ecdsa.PrivateKey, contractAddress common.Address, contractABI string, SellAddress common.Address, value *big.Int) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()
	// 代币合约地址
	tokenAddress := SellAddress
	// 解析代币合约ABI
	abiByte, err := abi.JSON(strings.NewReader(contractABI))
	if err != nil {
		log.Fatalf("Failed to parse contract ABI: %v", err)
	}

	// 构建交易数据
	spender := contractAddress
	//value := big.NewInt(1000000000000) // 授权的代币数量

	approveData, err := abiByte.Pack("approve", spender, value.Mul(value, big.NewInt(1000)))
	if err != nil {
		log.Fatalf("Failed to pack approve data: %v", err)
	}

	// 构建交易参数
	nonce, err := client.PendingNonceAt(context.Background(), crypto.PubkeyToAddress(privateKey.PublicKey))
	if err != nil {
		log.Fatalf("Failed to retrieve nonce: %v", err)
	}

	gasPrice, err := client.SuggestGasPrice(context.Background())
	if err != nil {
		log.Fatalf("Failed to retrieve gas price: %v", err)
	}

	//gasLimit := uint64(300000) // 自定义燃气限制
	gasLimit, err := client.EstimateGas(ctx, ethereum.CallMsg{
		From: crypto.PubkeyToAddress(privateKey.PublicKey), // 设置调用者地址
		To:   &tokenAddress,
		Data: approveData,
	})
	// 创建交易
	tx := types.NewTransaction(nonce, tokenAddress, big.NewInt(0), gasLimit, gasPrice, approveData)
	ChainID, err := client.ChainID(ctx)
	if err != nil {
		return
	}
	// 签名交易
	signedTx, err := types.SignTx(tx, types.NewEIP155Signer(ChainID), privateKey)
	if err != nil {
		log.Fatalf("Failed to sign transaction: %v", err)
	}

	// 发送交易
	err = client.SendTransaction(context.Background(), signedTx)
	if err != nil {
		log.Fatalf("Failed to send transaction: %v", err)
	}

	log.Printf("Approval transaction sent: %s\n", signedTx.Hash().Hex())
}
